热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

磁盘驱动器|也就是_Windows虚拟磁盘驱动开发(采用原始办法实现类似Storport框架的相同功能)

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Windows虚拟磁盘驱动开发(采用原始办法实现类似Storport框架的相同功能)相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Windows 虚拟磁盘驱动开发(采用原始办法实现类似Storport框架的相同功能)相关的知识,希望对你有一定的参考价值。


其实以前讲述windows平台下的磁盘驱动的开发挺多,而且时间也是非常早。


以下连接:


https://blog.csdn.net/fanxiushu/article/details/9903123?spm=1001.2014.3001.5501


https://blog.csdn.net/fanxiushu/article/details/11713357?spm=1001.2014.3001.5501


讲述的主要就是以 Storport 和 Scsiport 框架为主的windows平台的虚拟磁盘驱动开发,


并且在CSDN上提供了一个基于这两个框架的例子代码:


https://download.csdn.net/download/fanxiushu/5994583?spm=1001.2014.3001.5501



看看写博客的时间,距今快10年了,一个非常难言而又漫长的岁月(相对日新月异的信息技术而言)


然而仔细分析却会发现,其核心和本质的东西,并没改变多少,基本保持着多年前的哪些框架和原理。


除非在信息技术和操作系统领域发生了颠覆性的革命(比如以生物计算代替硅基电路),


否则经过人们多年努力建立起来的基础核心,都不会有太大变化。


比如现在的电脑,各种终端,服务器等都遵循着 冯·诺依曼型计算机的基本规则。



回到我们的windows虚拟磁盘驱动。



为何想到要用原始办法来开发类似Storport框架的虚拟磁盘驱动?


估计是闲的蛋疼吧。



又或者为了彰显曾经无法理解和实现的,现在具备了一定基础,再来实现,却发现变得异常的简单。


记得以前开发winxp下的Scsiport框架的虚拟磁盘驱动,非常的麻烦,


不但要解决虚拟模拟部分,安装驱动电脑还得重启好几次才能安装成功。



以前讲述过虚拟磁盘驱动,


有基于filedisk模型的,这个纯粹就是在文件系统下面挂一个接口,


直接接收来自文件系统转化而成的数据块读写指令, 不能被磁盘管理器识别,也不能被windows当成真正的“设备”,


但好处也显而易见,模型简单易懂,很快就能实现,


而且节省了windows下驱动命令的弯弯绕绕的浪费(这个纯粹基于心理上,现在的电脑性能根本不在乎这些)



有基于Storport和scsiport框架的,


而Storport 属于windows中目前几乎所有磁盘驱动(包括虚拟磁盘,更包括真实的磁盘)通用的框架。


因此如果需要开发不管是虚拟的,还是基于硬件的,掌握Storport框架,基本就可以了。



而我们今天要讲述的,则是从更底层的,更本质角度去实现虚拟磁盘驱动。


简单的说,使用原始代码,自己码代码来实现类似Storport框架一样的磁盘驱动,


因为Storport框架的代码我没看过,也不清楚Storport框架底层代码是如何实现的。


但是根据windows的wdm驱动的运行规律,PDO和FDO等基本常识,


Storport实现的大致流程,跟我准备讲述的应该比较接近,或者总体思路比较接近。



开始之前,我们需要一些准备知识。


首先熟悉PDO和FDO等基本概念。


需要熟悉windows平台下通用的总线驱动开发流程,


熟悉SCSI磁盘相关命令。


这些准备知识,这里不再具体阐述。



而运气好稍好,以上我都具备,因此从底层码代码来实现虚拟磁盘驱动,就显得比较容易了。



首先,我们抛开了storport 框架,自己码代码来实现虚拟磁盘驱动,是需要建立在虚拟总线驱动之上的。



当初为了实现USB虚拟总线驱动,曾经非常认认真真的研究了微软的toaster例子,而且是研究wdm的,不是kmdf框架。


为何需要这么做,那是因为window7,8 这些的系统不像windows10,有专门提供UDE和UCX框架来实现usb控制器的虚拟。


winxp,win7,win8就只能从更底层的总线驱动来实现USB主机控制器的模拟。


而且USB相关的指令是异常的繁多。



当初为了开发usb总线驱动,还重新构建了基于wdm模型的总线驱动框架代码,其实主要是处理 IRP_MJ_PNP, IRP_MJ_POWER命令,


别看只有两个命令,其实处理的内容非常多,还得考虑如何管理PDO等内容。


自己实现的这个框架代码,目前用在了 USB虚拟主机控制器的开发上(以前的文章阐述过usb虚拟总线的开发,有兴趣可去查阅),


也用在了 Indirect Display Driver (win10的虚拟显示器驱动)的总线枚举上,


同时也用在了目前讨论的虚拟磁盘开发上,然后发现:虚拟总线驱动这玩意用处还挺多。



打开设备管理器,查看 “存储控制器” 和 “ 磁盘驱动器” 里边的内容,


会发现里边对应一个磁盘控制器驱动(存储控制器)和一个或者多个对应的磁盘(磁盘驱动器),


不同电脑,对应的磁盘控制器不一定在 “存储控制器” 里边,有可能是对应着“IDE ATA/ATAPI 控制器” 等,


反正不管怎么说,一块磁盘,都会对应着磁盘控制器驱动。


如果我们把这个控制器驱动称作 FDO ,把对应的每个磁盘称作 PDO,现在我们来具体分析FDO和PDO的对应关系。



为了更好理解,用下面的实物图来说明,


这个是我笔记本电脑上的磁盘情况,使用Devicetree工具软件分析磁盘驱动里边的设备情况:











在上图中,左边是“设备管理器”,中间是Devicetree显示的内容,右边是Apple磁盘显示的属性。


Apple 是笔记本电脑上的唯一块真实硬盘


设备管理器里 “Apple Solid State Drive Device“ 是Apple磁盘控制器驱动。


它的驱动名是 AppleSSD.sys,这可以从右边的属性里看到。驱动是基于Storport框架的(现在绝大部分磁盘驱动基本都是基于此框架),


在中间Devicetree软件里可以看到 \\Driver\\AppleSSD 驱动里创建了两个Device设备,我们重点关注 \\Device\\00000037 。


可以看到它上面挂载了\\Device\\Harddisk0\\DR0, 接着有挂载了 \\Driver\\partmgr,


很显然 \\Device\\00000037 是块磁盘设备, 是最底层的 PDO 设备。


同时从右边属性里可以看到,它是 “Apple APPLE SSD AP0512 SCSI Disk Device” ,


也就是设备管理器“磁盘驱动器”里边的 对应的磁盘。



这个关系也就挺明显了:


Apple Solid State Drive Device 磁盘控制器驱动(也就是FDO)里创建了某块磁盘的 PDO,并且管理着这个磁盘PDO的行为模式。



另外设备管理器还出现了


“Fanxiushu Primitive Virtual SCSI Adapter” 和 “Fanxiushu xFsRedir Virtual SCSI Adapter”


两个 虚拟磁盘控制器,


其中xFsRedir对应为xFsRedir软件开发的扩展虚拟磁盘驱动,是基于Storport框架的。


而Primitive 则是本文讨论的,直接基于底层的虚拟总线驱动实现的虚拟磁盘控制器。


他们都能同时管理多块磁盘设备。



理清了上面的关系,我们会发现,基于原始虚拟总线驱动开发虚拟磁盘的总体框架,变得异常的简单


(当然得先熟悉通用的虚拟总线驱动和FDO,PDO这些基本的东西),



我们甚至可以首先开发一个通用的虚拟总线驱动程序,驱动里边创建一个或多个PDO设备,


PDO怎么创建则取决于你以后打算如何规划这个磁盘设备,现在就假设简单的创建一个PDO设备。



现在的问题是,如何把这个通用的虚拟总线驱动变成一个虚拟磁盘驱动,


让windows系统认为我们开发的是一块磁盘驱动程序。


首先,在制作 inf安装配置文件的时候,把[Version]里的 CLASS设置成 SCSIAdapter类,


ClassGUID 设置成 4D36E97B-E325-11CE-BFC1-08002BE10318。



在这个SCSIAdapter类里面,windows会把驱动当成是磁盘控制器,自然就会发送一些磁盘相关的命令到我们的驱动。


于是接下来的重头戏,就是得正确响应这些跟磁盘相关的命令。


(当然我们在调用IoCreateDEvice创建设备的时候,设置 FILE_DEVICE_DISK,表示我们创建的设备类型是 磁盘类型。)


而接受磁盘相关命令的主要是PDO设备。



以下是一些伪代码来描述这样一个总体框架。



NTSTATUS DriverEntry(.....)



........


DriverObject->DriverExtension->AddDevice = AddDevice;


DriverObject->DriverUnload = DriverUnload;



DriverObject->MajorFunction[IRP_MJ_PNP] = pnp_dispatch;


DriverObject->MajorFunction[IRP_MJ_POWER] = power_dispatch;



DriverObject->MajorFunction[IRP_MJ_CREATE] =


DriverObject->MajorFunction[IRP_MJ_CLEANUP] =


DriverObject->MajorFunction[IRP_MJ_CLOSE] =


DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =


DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =


DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = vscsi_dispatch;


..........



static NTSTATUS vscsi_dispatch(PDEVICE_OBJECT deviceObject, PIRP Irp)



NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;




PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);


base_exts_t* base = (base_exts_t*)deviceObject->DeviceExtension;



if (base->devType == 1) // FDO


fdo_exts_t* fdo = (fdo_exts_t*)base;


/


switch (irpStack->MajorFunction)



case IRP_MJ_CREATE:


case IRP_MJ_CLEANUP:


case IRP_MJ_CLOSE:


case IRP_MJ_DEVICE_CONTROL:


return ioctl_dispatch_function(deviceObject, Irp);



case IRP_MJ_SYSTEM_CONTROL:


return wmi_system_control(deviceObject, Irp); ///



default:


status = STATUS_INVALID_DEVICE_REQUEST;


DPT("V: --FDO: Not Process MJ=[0x%X]\\n", irpStack->MajorFunction);



break;




//



else // PDO


/


switch (irpStack->MajorFunction)



case IRP_MJ_CREATE:


case IRP_MJ_CLEANUP:


case IRP_MJ_CLOSE:


DPT("V: ++PDO: Do Raw Create Close. MJ=0x%X\\n", irpStack->MajorFunction ); 2016-06-11


status = STATUS_SUCCESS;


break;



case IRP_MJ_DEVICE_CONTROL:


return pdo_devicecontrol_dispatch(deviceObject, Irp, irpStack, (pdo_exts_t*)base);



case IRP_MJ_INTERNAL_DEVICE_CONTROL:


return pdo_srb_trans_dispatch(deviceObject, Irp, irpStack, (pdo_exts_t*)base);



default:


status = STATUS_INVALID_DEVICE_REQUEST;


DPT("V: ++PDO: Not Process MJ=[0x%X]\\n", irpStack->MajorFunction);


break;




/




/


return complete_irp(Irp, status, 0);




以上 vscsi_dispatch 派遣函数中,


其中 ioctl_dispatch_function 函数处理的FDO相关IOCTL,这个IOCTL可以传递我们自己定义的一些数据,


比如我们打算把虚拟磁盘的读写数据传输到应用层来处理,以及其他一些自定义命令。


总之这个函数里不传输windows系统命令。



而 pdo_devicecontrol_dispatch 和 pdo_srb_trans_dispatch 函数则是必须响应windows系统下发的IOCTL命令。


其中 pdo_devicecontrol_dispatch 响应windows系统定义的命令,目前通过测试 其中


IOCTL_STORAGE_QUERY_PROPERTY 命令是必须正确响应并处理的,否则系统不会认为这是磁盘驱动。


当然还包括其他一些命令,具体可以在不同系统下测试,然后再做处理。



pdo_srb_trans_dispatch 函数处理的就是核心的磁盘通信了,基本都是SCSI命令。


这个的处理基本和 Storport框架里边关于 SRB (SCSI_REQUEST_BLOCK 结构)的处理基本一致。


srb通过IRP获取,如下:


PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);


PSCSI_REQUEST_BLOCK srb = irpStack->Parameters.Scsi.Srb;


PCDB cdb = (PCDB)srb->Cdb;



因此如果你熟悉 Storport框架,以及scsi命令的话,这个也不是难事。


因为在以前阐述虚拟磁盘驱动的时候,阐述过相关内容,


这里也就不再赘述了。



最近计划着重温多年前的关于无盘启动的技术,其实当年(大概是10年前,因为根据cdsn博客上写的文章的时间推断)


实现了winxp的无盘启动,到后来win7没成功,什么原因后来一直处于搁置,这次有机会看看能不能解决。


当然现在关于无盘启动的现成软件也挺多,


而且现在也并不如当初那么火热,毕竟技术在发展,现在使用云桌面构建通用的远程平台应该更合适。


无论如何,如果有空就折腾来玩玩。而且打算这次把虚拟磁盘换成目前新开发的这种原始总线驱动方式来进行无盘启动。



关于xFsRedir软件,也计划把Storport框架的扩展虚拟磁盘驱动换成这种原始总线驱动方式。


推荐阅读
  • 本文档提供了详细的MySQL安装步骤,包括解压安装文件、选择安装类型、配置MySQL服务以及设置管理员密码等关键环节,帮助用户顺利完成MySQL的安装。 ... [详细]
  • 理解HTTP状态码及其应用
    本文详细解析了HTTP状态码的分类及常见代码的意义,帮助开发者和用户更好地理解和解决网络请求中遇到的问题。 ... [详细]
  • 本文探讨了在使用 ClickOnce 部署方式时遇到的自动更新失败问题,包括本地安装与服务器安装的不同表现,并提供了详细的解决方案。 ... [详细]
  • 本文探讨了Flutter和Angular这两个流行框架的主要区别,包括它们的设计理念、适用场景及技术实现。 ... [详细]
  • 我们正在使用GNU Make来构建我们的系统,在makefile文件的末尾,我们通过一个名为Makedepends的包含来生成一系列的.d文件。然而,当文件被删除或移动时,依赖关系会中断,我们需要寻找一种方法来优雅地处理这种情况。 ... [详细]
  • 本文介绍了如何在Spring框架中配置和使用定时任务,包括初始化配置和动态启动定时器的方法。通过示例代码展示了如何利用Spring的TaskScheduler接口来创建和管理定时任务。 ... [详细]
  • 深入解析 Zend Guard 4 功能与配置
    本文旨在通过图文并茂的方式详细介绍 Zend Guard 4 的核心功能及其配置方法,特别适合英文阅读能力有限的技术人员。文中不仅提供了详细的步骤说明,还附带了实际操作中的注意事项,帮助读者更好地理解和应用这一工具。 ... [详细]
  • 本文深入探讨了HTML5中十五个重要的新特性,为开发者提供了详细的指南。 ... [详细]
  • Python安全实践:Web安全与SQL注入防御
    本文旨在介绍Web安全的基础知识,特别是如何使用Python和相关工具来识别和防止SQL注入攻击。通过实际案例分析,帮助读者理解SQL注入的危害,并掌握有效的防御策略。 ... [详细]
  • 正在学习操作系统开发,遇到一个内核在GRUB Legacy(0.97)中无法成功引导的问题。具体表现为输入内核命令后显示错误信息,尝试引导时GRUB挂起。 ... [详细]
  • 本文详细介绍了如何利用go-zero框架从需求分析到最终部署至Kubernetes的全过程,特别聚焦于微服务架构中的网关设计与实现。项目采用了go-zero及其生态组件,涵盖了从API设计到RPC调用,再到生产环境下的监控与维护等多方面内容。 ... [详细]
  • 本文旨在探讨计算机机房的有效管理与维护方法,包括合理的机房布局设计、高效的操作系统安装与恢复技术以及数据保护措施。随着信息技术教育的发展,计算机机房作为教学的重要组成部分,其稳定性和安全性直接影响到教学质量。文章分析了当前机房管理中存在的问题,并提出了针对性的解决方案。 ... [详细]
  • 本文将指导你如何通过自定义配置,使 Windows Terminal 中的 PowerShell 7 更加高效且美观。我们将移除默认的广告和提示符,设置快捷键,并添加实用的别名和功能。 ... [详细]
  • 本文介绍了JSP的基本概念、常用标签及其功能,并通过示例详细说明了如何在JSP页面中使用Java代码。 ... [详细]
  • 我的世界服务器修改圈地大小,我的世界圈地大小限制设置 ... [详细]
author-avatar
呆瓜.
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有